package com.example.musicproject_b.filter;

import com.alibaba.fastjson.JSONObject;
import com.auth0.jwt.exceptions.AlgorithmMismatchException;
import com.auth0.jwt.exceptions.SignatureVerificationException;
import com.auth0.jwt.exceptions.TokenExpiredException;
import com.auth0.jwt.interfaces.Claim;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.example.common.b_pojo.BAdminUser;
import com.example.common.utils.JWTUtils;
import com.example.service.Imp.UserDetailsServiceImp;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Map;

import static com.example.musicproject_b.Controller.AdminLoginController.USER_PREFIX;

@Component
public class JwtFilter extends OncePerRequestFilter {

    @Autowired
    private StringRedisTemplate stringredisTemplate;

    @Autowired
    private UserDetailsServiceImp userDetailsServiceimp;

    @Override
    protected void doFilterInternal(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, FilterChain filterChain) throws ServletException, IOException {
        String username = "";
        //获取token
        String token = httpServletRequest.getHeader("token");
        try {
        if (!StringUtils.hasText(token)) {
            //放行
            filterChain.doFilter(httpServletRequest, httpServletResponse);
            return;
        }
        // 检查 Redis 中是否存在 token
        DecodedJWT decodedJWT =JWTUtils.getTokenInfo(token);
        if (decodedJWT == null) {
            logger.error("token:无效");
            //放行
            filterChain.doFilter(httpServletRequest, httpServletResponse);
            return;
        }
        String id =decodedJWT.getClaims().get("id").asString();
        String redisToken = stringredisTemplate.opsForValue().get(USER_PREFIX + id);
        if (redisToken == null || !redisToken.equals(token)) {
            logger.error("Redis 中没有数据，请重新登录！");
            //放行
            filterChain.doFilter(httpServletRequest, httpServletResponse);
            return;
        }

            DecodedJWT tokenInfo = JWTUtils.getTokenInfo(token);
            JWTUtils.verify(token);
            username = tokenInfo.getClaim("username").asString();
            BAdminUser bAdminUser = (BAdminUser) userDetailsServiceimp.loadUserByUsername(username);
//            认证成功后创建一个UsernamePasswordAuthenticationToken对象，并将用户详细信息和权限信息传递给它。
            UsernamePasswordAuthenticationToken authentication =
                    new UsernamePasswordAuthenticationToken(bAdminUser, null, bAdminUser.getAuthorities());
//            身份验证时，就可以获取到当前请求的详细信息，如IP地址、请求参数等，以便进行安全验证。
            authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(httpServletRequest));
//            将创建的认证对象设置到SecurityContextHolder中，以便在整个应用程序中访问
            SecurityContextHolder.getContext().setAuthentication(authentication);
        } catch (NullPointerException e) {
            e.printStackTrace();
            logger.error("redis中没有数据，请重新登陆！");
        } catch (SignatureVerificationException e) {
            e.printStackTrace();
            logger.error("token:签名不一致");
        } catch (TokenExpiredException e) {
            e.printStackTrace();
            logger.error("token:token过期");
        } catch (AlgorithmMismatchException e) {
            e.printStackTrace();
            logger.error("token:算法不匹配");
        } catch (Exception e) {
            e.printStackTrace();
            logger.error("token:token无效");
        }
        filterChain.doFilter(httpServletRequest, httpServletResponse);
    }



}
